package gobase

import "time"

type TryLocker interface {
	TryLock() bool
	Unlock()
}

type RLocker interface {
	RLock()
	RUnlock()
}

func RLock(lk RLocker, fn func()) {
	lk.RLock()
	defer lk.RUnlock()
	fn()
}

type Locker interface {
	Lock()
	Unlock()
}

func Lock(lk Locker, fn func()) {
	lk.Lock()
	defer lk.Unlock()
	fn()
}

// 参数需要传入*sync.Mutex以操作原始锁
func TryLock(lk TryLocker, timeout time.Duration) bool {
	// 超时信号通道
	tm := time.After(timeout)

	// 短暂休眠时间，避免忙等待
	shortSleep := time.Microsecond * 100

	for {
		select {
		case <-tm:
			// 超时返回
			return false
		default:
			// 尝试获取锁
			if lk.TryLock() {
				return true
			}
			time.Sleep(shortSleep)
		}
	}
}

func TestLocker(lk TryLocker, timeout time.Duration) bool {
	if !TryLock(lk, timeout) {
		return false
	}
	lk.Unlock()
	return true
}
